/*

目的： 输入子系统+ 按键中断

参考文档：robin@ubuntu:~/work/kernel-rockchip-nanopi4-linux-v4.4.y/Documentation/input$ vi input-programming.txt
 实现pwr_key 基于输入子系统上报

针对输入设备对象来写的驱动
//1.声明输入设备对象
//2.创建输入设备对象
//3.初始化输入设备对象
//4.注册输入设备对象
//5.硬件初始化
//6.中断处理函数上报事件


测试insmod button_input_drv.ko  以后

创建节点/dev/input/event4 比如
也可以
cat    /sys/class/input/event4/devices/name 就是下面的	button_dev->name = "xyd power key button";
*/

#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>	



//1.声明输入设备对象
static struct input_dev *button_dev;
static int gpio_button, irqno;

//定义中断处理函数
static irqreturn_t button_handler(int irqno, void *dev)
{
	int value;
	value = gpio_get_value(gpio_button);
	if (value) 
		input_report_key(button_dev, KEY_A, 0); //0--松开
	else
		input_report_key(button_dev, KEY_A, 1); //1--按下
	input_sync(button_dev); //同步事件 上报结束,必须要上报

	
	printk("<kernel>call %s()\n", __func__); 
	return IRQ_HANDLED;
}


static int __init button_init(void)
{
	int ret;

	//2.创建输入设备对象
	button_dev = input_allocate_device();
	if (!button_dev) {
		printk("input_allocate_device fail\n");
		return  -ENOMEM;
	}

	//3.初始化输入设备对象
	//按键类型有几十种，内部有一个u32表示，设置对应标志位，置1
//	set_bit(EV_KEY, button_dev->evbit); //为输入设备对象设置事件类型

// 有800多个按键，内部一个数组，把对应位置1
//	set_bit(KEY_A, button_dev->keybit); //为输入设备对象设置键码
	

//下面写法也可以
	button_dev->evbit[0] = BIT_MASK(EV_KEY);																					
	button_dev->keybit[BIT_WORD(KEY_A)] = BIT_MASK(KEY_A);

	//设置输入设备对象的信息
	button_dev->name = "xyd power key button";
	button_dev->phys = "rk3399 powwer key";
	button_dev->id.vendor = 0x11;
	button_dev->id.product = 0x22;
	button_dev->id.version = 48;
	
	//4.注册输入设备对象
	ret = input_register_device(button_dev);
	if (ret) {
		printk("input_register_device fail \n");
		ret = -EBUSY;
		goto err_input_register_device;

	}

	//5.硬件初始化
	gpio_button = 5; //GPIO0_A5
	irqno = gpio_to_irq(gpio_button);
	ret = request_irq(irqno, button_handler, IRQ_TYPE_EDGE_BOTH, "pwr_key_Int", NULL);
	if (ret) {
		printk("request_irq fail\n");
		ret = -EFAULT;
		goto err_request_irq;
	}
	
	
	printk("call %s()\n", __func__);  
	return 0;

err_request_irq:
	input_unregister_device(button_dev);
err_input_register_device:
	input_free_device(button_dev);
	return ret;
	
}


static void __exit button_exit(void)
{
	free_irq(irqno,NULL);
	input_unregister_device(button_dev);
	input_free_device(button_dev);
	printk("call %s() @ %d\n", __FUNCTION__, __LINE__);  
	
}
module_init(button_init); 
module_exit(button_exit); 
MODULE_LICENSE("GPL"); 


